package com.adjaisd.scarecrow.service.impl;

import com.adjaisd.scarecrow.common.utils.GeoUtils;
import com.adjaisd.scarecrow.dto.GpsInfo;
import com.adjaisd.scarecrow.entity.Device;
import com.adjaisd.scarecrow.entity.DeviceGps;
import com.adjaisd.scarecrow.entity.DeviceStatus;
import com.adjaisd.scarecrow.mapper.DeviceGpsMapper;
import com.adjaisd.scarecrow.repo.TimeSeriesRepository;
import com.adjaisd.scarecrow.service.DeviceGpsService;
import com.adjaisd.scarecrow.service.DeviceService;
import com.adjaisd.scarecrow.service.DeviceStatusService;
import com.adjaisd.scarecrow.vo.DeviceGpsPointVO;
import com.adjaisd.scarecrow.vo.DeviceGpsVO;
import com.adjaisd.scarecrow.vo.GeoCoordinate;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author adjaisd
 * @since 2022-03-22
 */
@Service
public class DeviceGpsServiceImpl extends ServiceImpl<DeviceGpsMapper, DeviceGps> implements DeviceGpsService {

    @Autowired
    DeviceGpsMapper deviceGpsMapper;

    @Autowired
    DeviceService deviceService;

    @Override
    public DeviceGps getDeviceGps(Long number) {
        QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Device::getNumber, number)
                .gt(Device::getBindTime, 0L);
        List<Device> deviceList = deviceService.list(queryWrapper);
        if (deviceList.size() == 0) return null;
        Device device = deviceList.get(0);
        QueryWrapper<DeviceGps> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(DeviceGps::getNumber, number)
                .eq(DeviceGps::getId, device.getId());
        List<DeviceGps> gpsList = this.list(wrapper);
        if (gpsList.size() == 1) return gpsList.get(0);
        else return null;
    }

    @Autowired
    TimeSeriesRepository timeSeriesRepository;

    @Override
    public Boolean updateDeviceGPS(DeviceGps deviceGps) {
        DeviceGps gps = getDeviceGps(deviceGps.getNumber());
        GpsInfo gpsInfo = new GpsInfo();
        gpsInfo.setNumber(deviceGps.getNumber() + "");
        gpsInfo.setLat(deviceGps.getLatitude() + "");
        gpsInfo.setLon(deviceGps.getLongitude() + "");
        if (gps == null) {
            Device device = deviceService.getDeviceByNumber(deviceGps.getNumber());
            deviceGps.setId(device.getId());
            timeSeriesRepository.add(gpsInfo);
            return deviceGpsMapper.insert(deviceGps) > 0;
        } else {
            timeSeriesRepository.add(gpsInfo);
            return this.updateById(deviceGps);
        }
    }

    @Override
    public DeviceGps analysis(String topic, Map<String, Object> payloadMap) {
        if (!payloadMap.containsKey("number")) return null;
        Long number = Long.parseLong(payloadMap.get("number") + "");
        if (!payloadMap.containsKey("lat") || !payloadMap.containsKey("lon"))
            return null;
        System.out.println("解析GPS数据payloadMap = " + payloadMap);
        Double lat = Double.valueOf(payloadMap.get("lat") + "");
        Double lon = Double.valueOf(payloadMap.get("lon") + "");
        long time = new Date().getTime();
        DeviceGps gps = getDeviceGps(number);
        if (gps == null) {
            gps = new DeviceGps(null, number, lon, lat, time);
            updateDeviceGPS(gps);
            return null;
        }
        gps.setTime(time);
        gps.setLatitude(lat);
        gps.setLongitude(lon);
        return gps;
    }

    @Autowired
    DeviceStatusService deviceStatusService;

    @Override
    public DeviceGpsVO getAllDeviceGps(Long userId) {
        DeviceGpsVO deviceGpsVO = new DeviceGpsVO();
        int total = 0, alarm = 0, online = 0, status = 0, normal = 0;
        // 根据userId获取所有设备
        List<Device> deviceList = deviceService.getDeviceListByUID(userId);
        List<DeviceGpsPointVO> gpsPointVOList = new LinkedList<>();
        for (Device device : deviceList) {
            DeviceStatus deviceStatus = deviceStatusService.getDeviceStatusByID(device.getId());
            DeviceGps deviceGps = getDeviceGps(device.getNumber());
            if (deviceStatus == null || deviceGps == null) continue;

            DeviceGpsPointVO gpsPointVO = new DeviceGpsPointVO();
            // 更新统计数量
            total++;
            if (deviceStatus.getStatus()) status++;
            if (deviceStatus.getOnline()) online++;
            if (deviceStatus.getAlarm()) alarm++;
            if (deviceStatus.getStatus() && deviceStatus.getOnline() && !deviceStatus.getAlarm()) {
                gpsPointVO.setNormal(true);
                normal++;
            } else gpsPointVO.setNormal(false);
            gpsPointVO.setDeviceId(device.getId() + "");
            gpsPointVO.setNumber(device.getNumber() + "");
            gpsPointVO.setDeviceName(device.getName());
            gpsPointVO.setStatus(deviceStatus.getStatus());
            gpsPointVO.setOnline(deviceStatus.getOnline());
            gpsPointVO.setAlarmLevel(deviceStatus.getAlarmLevel());
            gpsPointVO.setLat(deviceGps.getLatitude());
            gpsPointVO.setLon(deviceGps.getLongitude());
            gpsPointVO.setTime(deviceGps.getTime());
            gpsPointVOList.add(gpsPointVO);
        }

        // 封装DeviceGpsVO
        deviceGpsVO.setTotal(total);
        deviceGpsVO.setStatus(status);
        deviceGpsVO.setOnline(online);
        deviceGpsVO.setAlarm(alarm);
        deviceGpsVO.setNormal(normal);
        deviceGpsVO.setDeviceGpsVOList(gpsPointVOList);

        // 获取中心点
        LinkedList<GeoCoordinate> geoList = new LinkedList<>();
        gpsPointVOList.forEach(gpsPointVO -> geoList.add(new GeoCoordinate(gpsPointVO.getLat(), gpsPointVO.getLon())));
        GeoCoordinate centerPoint = GeoUtils.getCenterPoint400(geoList);
        double maxDist = 0; // 最大距离
        for (GeoCoordinate geo : geoList)
            maxDist = Math.max(maxDist, GeoUtils.getDistance(centerPoint, geo));
        deviceGpsVO.setMaxDist(maxDist);
        deviceGpsVO.setGeoCoordinate(centerPoint);
        return deviceGpsVO;
    }

    private final GeoCoordinate center1 = new GeoCoordinate(38.125124, 111.724744);  //山西省, 太原市, 娄烦县
    private final GeoCoordinate center2 = new GeoCoordinate(33.765327, 103.829633);  //甘肃省, 甘南藏族自治州, 迭部县
    private final GeoCoordinate center3 = new GeoCoordinate(31.018405, 111.924444);  //湖北省, 宜昌市, 当阳市

    @Override
    public GeoCoordinate getRandomLocation(Long number) {
        DeviceGps deviceGps = getDeviceGps(number);
        GeoCoordinate tmp, cen;
        if (deviceGps != null) {
            cen = new GeoCoordinate(deviceGps.getLatitude(), deviceGps.getLongitude());
            tmp = GeoUtils.getRandomLocation(cen, 1000 * 10);//10千米
        } else {
            long time = new Date().getTime();
            if (time % 3 == 0) cen = center1;
            else if (time % 3 == 1) cen = center2;
            else cen = center3;
            tmp = GeoUtils.getRandomLocation(cen, 1000 * 300);//300千米
        }
        return tmp;
    }

}
